home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright (C) 1987 by Scott Mason, except where noted in the
- source code, All Rights Reserved.
-
- Permission is hereby granted for use by non-profit entities only.
- Distribution of this file, CHGPATH.EXE, and/or CHGPATH.DOC in any form
- for a fee is prohibited.
-
- Written by Scott Mason
- 4050 Jay Em Circle
- Ellicott City, MD 21043
-
- Written using the DeSmet C88 C compiler package, v2.51
-
- Acknowledgement and graditude is hereby given to:
-
- John M Sellens,
- who wrote the getpath & parse_path functions, and
- Dan Lewis,
- who wrote the execute_string (and subsequent)
- functions, obtained from a file called SETVAR.C.
- ------------------------------------------------------------------
- Purpose: Allows you the make permanent changes to the PATH
- environment string from the DOS command line without
- having to retype the entire PATH command string.
-
- */
-
- #include <stdio.h>
-
- char newpath[200] = "PATH ";
- char *np = newpath;
- char *cp;
- typedef char *char_ptr;
- char *get_path();
- char_ptr *parse_path();
- char *copyright = " Copyright (C) 1987 by Scott Mason, except where noted\n";
- char *copyright2 = " in the source code, All Rights Reserved.\n";
-
- main(argc,argv)
- int argc;
- char **argv;
- {
- int i;
-
- if (argc != 2)
- usage();
-
- cp = get_path(); /* get the PATH environment string */
-
- argv++;
- if (**argv == '+')
- addpath(++*argv);
- else if (**argv == '-')
- delpath(++*argv);
- else
- usage();
-
- } /* end main */
-
-
- addpath(p)
- char *p;
- {
-
- strcat(np,cp); /* concat current path setting onto newpath */
- strcat(np,";");
- strcat(np,p); /* concat the path to add onto newpath */
- execute_string(np);
- printf("%s\n",np);
-
- } /* end addpath */
-
-
- delpath(p)
- char *p;
- {
- int i, j;
- char_ptr *paths;
- char *s;
-
- s = p;
- while (*s) /* convert path to delete to upper case */
- {
- if (isalpha(*s))
- *s = toupper(*s);
- s++;
- }
-
- paths = parse_path(cp);
- if (paths != NULL)
- {
- for (i=0; paths[i]!=NULL; i++)
- { /* compare with the path to delete */
- if (strlen(p) != (j=strlen(paths[i])) || /* beats DeSmet strncmp bug */
- strncmp(p,paths[i],j))
- {
- strcat(np,paths[i]); /* if not ==, concat that path onto */
- strcat(np,";"); /* the newpath string */
- }
- }
- *(p = rindex(np,';')) = '\0'; /* get rid of that last ; */
- execute_string(np);
- printf("%s\n",np);
- }
- else
- printf("No path is set ...\n");
-
- } /* end delpath */
-
-
- usage()
- {
- puts("\nUsage: CHGPATH +newpath\n");
- puts(" to Add newpath to the current path setting\n");
- puts(" CHGPATH -oldpath\n");
- puts(" to Remove oldpath from the current path setting\n\n");
- puts(" Where newpath & oldpath must be valid paths.\n\n");
- exit(1);
-
- } /* end usage */
-
-
- /**********************************************************************/
-
-
- /* The following are two routines to make it easier to access the
- PATH environment variable. They are written for use with the
- DeSmet C Compiler. Known portability problems:
-
- - assembler code embedded in the C code
- - requires that code segment register (CS) be set to the
- same value as at program invocation so that the
- program segment prefix can be located. This would
- probably only be a problem if a "large model"
- compiler is used.
-
- The code is a little kludgy in places but...
- Any suggestions for improvements gratefully accepted.
- */
-
- /* Written by John M Sellens, April, 1984
- (c) Copyright 1984 John M Sellens
-
- Permission is granted to use, distribute and/or modify this code unless
- done for direct commercial profit. If you find these routines useful,
- modest contributions (monetary or otherwise) will be gratefully accepted.
- Author's name, address and this notice must be included in any copies.
- */
-
- char_ptr *parse_path(ps)
- char *ps;
- {
- /* Takes the path string returned by get_path and destroys it,
- by inserting NULL's and returning an array of pointers to
- characters that point to locations in the original path
- string. The pointer after the last pointer into the path
- string is NULL. If the path string is NULL, then NULL is
- returned.
- */
-
- int i, j, num;
- char_ptr *pa;
-
- if (ps[0] == '\0') /* no path */
- return(NULL);
-
- /* count the number of semi-colons, add 1 = number of paths */
-
- for (num=1, i=0; ps[i] != '\0'; i++)
- if (ps[i] == ';')
- num++;
-
- pa = (char_ptr *)malloc(sizeof(char_ptr) * (num+1));
- pa[num] = NULL;
-
- /* now loop through and point to each path */
-
- for (i=j=0; i<num; i++)
- {
- pa[i] = &ps[j];
- while(ps[j]!=';' && ps[j]!='\0')
- j++;
- ps[j++] = '\0';
- }
-
- return(pa);
- }
-
-
-
- char *get_path()
- {
- /* Returns a pointer to a string containing the value of
- the environment variable PATH. E.g. if PATH=A:\;B:\
- the string "A:\;B:\" is returned. If no PATH is set,
- an empty string is returned.
- */
-
- static int path_seg;
-
- /* these three declarations must be first so that they can be
- referred to by stack address near the end when copying
- the PATH variable */
-
- char *base, *path;
- int siz;
- char *next;
- char env_str[10]; /* leave a little extra space just in case */
- int i, done;
-
- #asm
-
- ; determine the segment that the environment starts at
- ; this requires that cs is set to the same value as at
- ; program entry i.e. 100H past the program segment prefix
-
- push es
- mov ax,cs
- sbb ax,10h
- mov es,ax
- mov ax,es:[2cH]
- pop es
- mov word get_path_path_seg_,ax
- #end
-
- /* look for the start of PATH= */
- /* there's always going to be at least one thing in environment */
-
- done = FALSE;
- next = 0;
- env_str[0] = '\0';
- while ((strncmp("PATH=",env_str,5) != 0) && !done)
- {
- base = next;
-
- /* set DS to path_seg */
-
- #asm
- push ds
- mov ds,word get_path_path_seg_
-
- #end
-
- if (base[0] == '\0')
- done = TRUE; /* no more variables to look at */
-
- else
- { /* now copy 5 characters into memory */
- for (i=0; i<5; i++)
- env_str[i] = base[i]; /* ok since env_str is on stack */
-
- /* now set next to first character after end of this string */
-
- while ((next++)[0] != '\0')
- ;
- }
- /* reset DS */
- #asm
- pop ds
- #end
-
- }
- if (done) { /* no PATH environment variable set */
- path = (char *)malloc(1);
- path[0] = '\0';
- } else {
- siz = next - base - 5;
- path = (char *)malloc(siz);
- base += 5; /* skip over 'PATH=' */
- /* copy the PATH string to path */
- #asm
- push cx
- push es
- push ds
- mov cx,ds
- mov es,cx
- mov ds,word get_path_path_seg_
- mov si,word [bp-2] ;base
- mov di,word [bp-4] ;path
- mov cx,word [bp-6] ;siz
- rep movsb
- pop ds
- pop es
- pop cx
- #end
- }
- return(path);
-
- }
- /******************************************************************/
- /*
- The following little program can set an environment variable
- whose name is the first command line argument, and whose new
- value is the second command line argument. For example, to
- set environment variable XYZ to a value of HELLO, you would
- run this program using the command SETVAR XYZ HELLO.
-
- The *PURPOSE* of this piece of code is to illustrate an un-
- documented DOS interrupt entry point (2Eh) that will execute
- *ANY* DOS command *WITHOUT* having to load another copy of
- COMMAND.COM. Not only is it faster, but it is the ONLY way
- to set an environment variable (short of peeking and poking
- around into memory). You *CAN'T* set an environment variable
- with the command exec("COMMAND.COM", "/CSETXYZ=HELLO") because
- when the second copy of COMMAND.COM is loaded, it gets its
- very own environment (a duplicate of the parent's). Although
- the SET command WILL modify that duplicate copy, it won't
- modify the parent's!
-
- When I said that interrupt 2Eh can be used to execute *ANY*
- DOS command, I meant just that! You can leave off the filename
- extension (as you normally do at the command line), and it will
- perform the normal search for COM, EXE, and BAT files to execute,
- or even execute built-in commands as we've seen above.
-
- Enjoy!
-
- Dan Lewis, owner
- Key Software Products
- 440 Ninth Avenue
- Menlo Park, CA 94025
- (415) 364-9847
-
- */
-
- Execute_String(s)
- char *s;
- {
- long vec22, vec23, vec24 ;
- long Get_Vec() ;
- static char bfr[81];
-
- strcpy(bfr + 1,s) ;
- *bfr = strlen(bfr + 1) ;
- strcat(bfr + 1,"\r") ;
-
- /* preserve cntrl-break, terminate, and critical error vectors */
- vec22 = Get_Vec(0x22) ;
- vec23 = Get_Vec(0x23) ;
- vec24 = Get_Vec(0x24) ;
-
- Release_Memory() ;
- Exec(bfr) ; /* execute command */
-
- /* reset cntrl-break, terminate, and critical error vectors */
- Set_Vec(0x22,vec22) ;
- Set_Vec(0x23,vec23) ;
- Set_Vec(0x24,vec24) ;
- }
-
- Exec(s)
- char *s ;
- {
- #asm
- push ds
- push bp
- mov cs:WORD save_ss,ss
- mov cs:WORD save_sp,sp
- mov si,[bp+4]
- int 2Eh
- mov ss,cs:WORD save_ss
- mov sp,cs:WORD save_sp
- pop bp
- pop ds
- jmp Rtn
-
- save_ss:dw 0
- save_sp:dw 0
- save_ds:dw 0
- save_bp:dw 0
-
- Rtn:
- #end
- }
-
-
- Release_Memory()
- {
- if (Release())
- {
- puts("Release Memory Failure\n") ;
- exit(1) ;
- }
- }
-
-
- Release()
- {
- #asm
- mov ax,cs
- sub ax,0010h
- mov es,ax
- mov bx,ds
- add bx,1000h
- sub bx,ax
- mov ah,4Ah
- int 21h
- mov ax,0
- jnc R_Rtn
- inc ax
- R_Rtn:
- #end
- }
-
-
- long Get_Vec(vector)
- unsigned vector ;
- {
- #asm
- mov ah,35h
- mov al,BYTE [bp+4]
- int 21h
- mov ax,bx
- mov dx,es
- #end
- }
-
-
- Set_Vec(vector,addr)
- unsigned vector ;
- long addr ;
- {
- #asm
- mov ah,25h
- mov al,BYTE [bp+4]
- mov bx,WORD [bp+6]
- mov es,WORD [bp+8]
- int 21h
- #end
- }
-
-